package com.streamer.app.fragment

import android.app.Activity
import android.content.Intent
import android.content.Context
import android.graphics.Color
import android.media.MediaCodec
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.WindowManager
import android.widget.EditText
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.doOnLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.alivc.live.annotations.AlivcLiveMode
import com.alivc.live.pusher.AlivcAudioAACProfileEnum
import com.alivc.live.pusher.AlivcEncodeModeEnum
import com.alivc.live.pusher.AlivcFpsEnum
import com.alivc.live.pusher.AlivcLiveBase
import com.alivc.live.pusher.AlivcLivePushCameraTypeEnum
import com.alivc.live.pusher.AlivcLivePushConfig
import com.alivc.live.pusher.AlivcPreviewOrientationEnum
import com.alivc.live.pusher.AlivcResolutionEnum
import com.alivc.live.pusher.AlivcVideoEncodeGopEnum
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.streamer.app.R
import com.streamer.app.adapter.CoursewareAdapter
import com.streamer.app.bean.CoursewareInfoBean
import com.streamer.app.bean.liveProductBean
import com.streamer.app.utils.BottomSheetUtils
import com.streamer.app.widget.WhiteboardDrawingView
import io.keyss.view_record.recording.ViewLiveRecorder
import io.keyss.view_record.video.EncoderErrorCallback
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.lang.reflect.ParameterizedType

/**
 *  BaseFragment 基类BaseFragment
 */
abstract class BaseFragment<T : ViewBinding> : Fragment() {




    var viewMode = com.streamer.app.utils.api.ViewModel()

    var currentPage = 1
    var pageSize = 99
    val mAlivcLivePushConfig = AlivcLivePushConfig()
    var coursewareList: MutableList<CoursewareInfoBean> = mutableListOf()

    private lateinit var adapter: CoursewareAdapter

    protected fun <Y : ViewModel> createViewModel(clazz: Class<Y>): Y {
        return ViewModelProvider(this)[clazz]
    }

    private val viewLiveRecord = ViewLiveRecorder()
    private var mTimerJob: Job? = null


    protected lateinit var _binding: T
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {
        try {
            val cls =
                ((javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<*>)
            val method = cls.getDeclaredMethod("inflate", LayoutInflater::class.java)
            _binding = method.invoke(null, inflater) as T
            return _binding.root
        } catch (e: Exception) {
            Log.e("xxxxx", "setcontent error msg:${e.message}")
        }

        return super.onCreateView(inflater, container, savedInstanceState)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initView()
        AlivcLiveBase.registerSDK()

        // 初始化推流配置类

// 设置推流模式，默认普通推流模式
        mAlivcLivePushConfig.livePushMode = AlivcLiveMode.AlivcLiveBasicMode

// 设置分辨率，建议使用540P以提高兼容性
        mAlivcLivePushConfig.resolution = AlivcResolutionEnum.RESOLUTION_540P

// 设置帧率，默认20fps
        mAlivcLivePushConfig.setFps(AlivcFpsEnum.FPS_25)

// 设置视频编码Gop，单位秒，默认2秒
        mAlivcLivePushConfig.setVideoEncodeGop(AlivcVideoEncodeGopEnum.GOP_TWO)

// 开启码率控制，默认为true
        mAlivcLivePushConfig.isEnableBitrateControl = true

// 设置横竖屏，默认为竖屏，可设置home键向左或向右横屏
        mAlivcLivePushConfig.setPreviewOrientation(AlivcPreviewOrientationEnum.ORIENTATION_PORTRAIT)

// 设置音频编码模式，默认AAC-LC
        mAlivcLivePushConfig.audioProfile = AlivcAudioAACProfileEnum.AAC_LC

// 设置视频编码模式，默认硬编
        mAlivcLivePushConfig.videoEncodeMode = AlivcEncodeModeEnum.Encode_MODE_HARD

// 设置音频编码模式，默认软编
        mAlivcLivePushConfig.audioEncodeMode = AlivcEncodeModeEnum.Encode_MODE_SOFT

// 设置摄像头前后置，默认前置
        mAlivcLivePushConfig.setCameraType(AlivcLivePushCameraTypeEnum.CAMERA_TYPE_FRONT)

    }


    /**
     * 显示带数据的课件管理弹窗
     */
    fun showCoursewareDialogWithData(
        context: Activity,
        coursewareList: MutableList<CoursewareInfoBean>,
        onFileSelectedListener: ((CoursewareInfoBean) -> Unit)? = null,
        onAddFileClick: ((Array<String>) -> Unit)? = null,
        onDelFileClick: ((CoursewareInfoBean) -> Unit)? = null

    ): BottomSheetDialog {
        val dialog = BottomSheetDialog(context)
        val view = LayoutInflater.from(context).inflate(R.layout.bottom_courseware, null)
        dialog.setContentView(view)

        // 设置弹窗属性
        dialog.setCancelable(true)
        dialog.setCanceledOnTouchOutside(true)

        // 初始化控件
        val etSearch = view.findViewById<EditText>(R.id.etSearch)
        val ivSearch = view.findViewById<ImageView>(R.id.iv_search_courseware)
        val ivAdd = view.findViewById<ImageView>(R.id.ivAddFile)
        val ivClose = view.findViewById<ImageView>(R.id.iv_close_courseware)
        val rvCourseware = view.findViewById<RecyclerView>(R.id.rv_courseware_list)

        // 设置RecyclerView
        rvCourseware.layoutManager = LinearLayoutManager(context)

        // 创建适配器并设置数据
        adapter = CoursewareAdapter(coursewareList) { courseware, position, action ->
            when (action) {
                "select" -> {
                    // 选择课件
                    Log.d("WhiteboardFragment", "$position    选择了课件: ${courseware.fileName}")
                    onFileSelectedListener?.invoke(courseware)

                    dialog.dismiss()
                }

                "play" -> {
                    // 播放课件
                    Log.d("WhiteboardFragment", "$position  播放课件: ${courseware.fileName}")
                    onFileSelectedListener?.invoke(courseware)
                }

                "delete" -> {
                    // 删除课件
                    Log.d("WhiteboardFragment", "$position  删除课件: ${courseware.fileName}")
                    // 从列表中移除项目
                    val position = coursewareList.indexOfFirst { it.id == courseware.id }
                    if (position != -1) {
                        coursewareList.removeAt(position)
                        // 通知适配器数据已更改
                        viewMode.delCourseware(courseware.id)
                        adapter.notifyItemRemoved(position)
                    }
                    onDelFileClick?.invoke(courseware)
                }

                "long_click" -> {
                    // 长按操作
                    Log.d("WhiteboardFragment", " $position  长按课件: ${courseware.fileName}")
                }
            }
        }
        rvCourseware.adapter = adapter

        // 设置监听器
        ivClose.setOnClickListener { dialog.dismiss() }

        ivSearch.setOnClickListener {
            val keyword = etSearch.text.toString().trim()
            // 这里可以实现搜索功能
            Log.d("WhiteboardFragment", "搜索课件: $keyword")
        }

        ivAdd.setOnClickListener {
            // 由调用方触发系统文件选择器
            val supportedMimeTypes = arrayOf(
                "application/pdf",
                "application/msword",
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                "application/vnd.ms-powerpoint",
                "application/vnd.openxmlformats-officedocument.presentationml.presentation",
                "image/jpeg",
                "image/png"
            )
            onAddFileClick?.invoke(supportedMimeTypes)
        }

        dialog.show()
        return dialog
    }
     val openDocumentLauncher = registerForActivityResult(
        ActivityResultContracts.OpenDocument()
    ) { uri ->
        try {
            if (uri == null) return@registerForActivityResult

            val context = requireContext().applicationContext
            context.contentResolver.takePersistableUriPermission(
                uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
            )

            val fileName = BottomSheetUtils.getFileName(context, uri) ?: run {
                Toast.makeText(context, "无法获取文件名", Toast.LENGTH_LONG).show()
                return@registerForActivityResult
            }

            // 检查文件类型，区分课件和视频
            val mimeType = context.contentResolver.getType(uri)
            val isVideoFile = mimeType?.startsWith("video/") == true

            if (isVideoFile) {
                // 处理视频文件 - 保存到本地插播列表
                if (!BottomSheetUtils.checkFileSize(context, uri, 500)) { // 视频文件允许更大
                    Toast.makeText(context, "视频文件大小超过限制(500MB)", Toast.LENGTH_LONG).show()
                    return@registerForActivityResult
                }
                
                BottomSheetUtils.saveLocalVideo(context, fileName, uri.toString())
                BottomSheetUtils.refreshLocalPlayList()
                Toast.makeText(context, "已添加视频: $fileName", Toast.LENGTH_SHORT).show()
            } else {
                // 处理课件文件
                if (!BottomSheetUtils.isSupportedFileFormat(fileName)) {
                    Toast.makeText(context, "不支持的文件格式", Toast.LENGTH_LONG).show()
                    return@registerForActivityResult
                }

                if (!BottomSheetUtils.checkFileSize(context, uri, 200)) {
                    Toast.makeText(context, "文件大小超过限制", Toast.LENGTH_LONG).show()
                    return@registerForActivityResult
                }

                viewMode.uploadCourseware(context, uri)
                Toast.makeText(context, "已选择文件: $fileName", Toast.LENGTH_SHORT).show()
            }

        } catch (e: Exception) {
            Log.e("BaseFragment", "File selection error", e)
            Toast.makeText(requireContext(), "错误: ${e.message}", Toast.LENGTH_LONG).show()
        }
    }


    abstract fun initView()

    // region Brush picker helpers (shared)
    protected fun Int.dp(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()

    protected class ColorVH(private val v: View) : RecyclerView.ViewHolder(v) {
        fun bind(color: Int, onPicked: (Int) -> Unit) {
            v.background = android.graphics.drawable.GradientDrawable().apply {
                shape = android.graphics.drawable.GradientDrawable.RECTANGLE
                cornerRadius = 8f
                setColor(color)
            }
            v.setOnClickListener { onPicked(color) }
        }
    }

    protected fun showBrushPicker(
        anchorFragment: Fragment,
        drawingView: WhiteboardDrawingView,
        isEraser: Boolean,
        isBottom: Boolean=false
    ) {
        val ctx = anchorFragment.requireContext()
        val view = LayoutInflater.from(ctx).inflate(R.layout.dialog_brush_picker, null)
        val iv1 = view.findViewById<ImageView>(R.id.iv_line_1)
        val iv2 = view.findViewById<ImageView>(R.id.iv_line_2)
        val iv3 = view.findViewById<ImageView>(R.id.iv_line_3)
        val iv4 = view.findViewById<ImageView>(R.id.iv_line_4)
        val rv = view.findViewById<RecyclerView>(R.id.rv_colors)

        fun clearThicknessBg() {
            iv1.background = null
            iv2.background = null
            iv3.background = null
            iv4.background = null
        }
        fun applyWidth(w: Float, v: View) {
            if (isEraser) {
                // 橡皮模式下也同步更新画笔粗细与圆形橡皮半径，保证切回画笔立即生效
                drawingView.setEraserWidth(w)
                drawingView.setStrokeWidth(w)
                drawingView.setWhiteEraserRadius(w)
            } else {
                drawingView.setStrokeWidth(w)
            }
            clearThicknessBg()
            v.setBackgroundResource(R.drawable.tool_button_selected)
        }
        iv1.setOnClickListener { applyWidth(6f, iv1) }
        iv2.setOnClickListener { applyWidth(10f, iv2) }
        iv3.setOnClickListener { applyWidth(16f, iv3) }
        iv4.setOnClickListener { applyWidth(24f, iv4) }

        val currentWidth = if (isEraser) drawingView.getEraserWidth() else drawingView.getStrokeWidth()
        when {
            currentWidth < 8f -> iv1.performClick()
            currentWidth < 13f -> iv2.performClick()
            currentWidth < 20f -> iv3.performClick()
            else -> iv4.performClick()
        }

        val colors = arrayOf(
            "#FF9502","#FFBE31","#F9E71F","#ED4844","#1F5DFF","#4FE4C1",
            "#03C9F5","#FC9D9A","#8C5628","#407505","#2ACF42","#9B1BFE",
            "#8F8E93","#424242","#000000","#FFFFFF"
        )
        rv.layoutManager = GridLayoutManager(ctx, 4)
        val startColor = if (isEraser) drawingView.getStrokeColor() else drawingView.getStrokeColor()
        rv.adapter = object : RecyclerView.Adapter<ColorVH>() {
            var selectedPos = colors.indexOfFirst {
                it.equals(String.format("#%06X", 0xFFFFFF and startColor), true)
            }.let { if (it < 0) 0 else it }

            override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ColorVH {
                val v = View(ctx)
                val lp = RecyclerView.LayoutParams(20.dp(ctx), 20.dp(ctx))
                lp.setMargins(0, 5.dp(ctx), 0, 5.dp(ctx))
                v.layoutParams = lp
                return ColorVH(v)
            }

            override fun getItemCount() = colors.size
            override fun onBindViewHolder(holder: ColorVH, position: Int) {
                val original = Color.parseColor(colors[position])
                val display = if (isEraser) Color.argb(128, Color.red(original), Color.green(original), Color.blue(original)) else original
                holder.bind(display) { _ ->
                    // 无论是否在橡皮模式，都更新画笔颜色，确保返回画笔后立即生效
                    drawingView.setStrokeColor(original)
                    val old = selectedPos
                    selectedPos = position
                    notifyItemChanged(old)
                    notifyItemChanged(selectedPos)
                }
                val gd = android.graphics.drawable.GradientDrawable().apply {
                    shape = android.graphics.drawable.GradientDrawable.RECTANGLE
                    cornerRadius = 8f
                    setColor(display)
                    if (position == selectedPos) setStroke(2.dp(ctx), Color.parseColor("#4D3A8BFF"))
                }
                holder.itemView.background = gd
            }
        }

        val dialog = MaterialAlertDialogBuilder(ctx).setView(view).setCancelable(true).create()
        dialog.show()
        dialog.window?.let {
            val dm = ctx.resources.displayMetrics
            val width = (dm.widthPixels * 0.6).toInt()
            val height = (dm.heightPixels * 0.5).toInt()
            it.setLayout(width, height)
            val lp = it.attributes
            if(isBottom){
                lp.gravity = android.view.Gravity.BOTTOM

            }else{
                lp.gravity = android.view.Gravity.TOP

            }
            lp.y = -100
            it.attributes = lp
            it.setBackgroundDrawableResource(android.R.color.transparent)
        }
    }
    // endregion

    // region MQTT lifecycle helpers
    protected open fun mqttTopics(): List<String> = emptyList()
    protected open fun onMqttMessage(topic: String, payload: String) {}
    private val mqtt by lazy { com.streamer.app.utils.MqttManager.getInstance() }

    override fun onStart() {
        super.onStart()
        try {
            mqtt.addMessageCallback(object : com.streamer.app.utils.MqttManager.MessageCallback {
                override fun onMessageReceived(topic: String, message: String) {
                    onMqttMessage(topic, message)
                }
                override fun onConnectionStatusChanged(connected: Boolean) {}
            })
            mqttTopics().forEach { topic -> mqtt.subscribe(topic) { _, _ -> } }
        } catch (_: Exception) {}
    }

    override fun onStop() {
        try {
            mqttTopics().forEach { topic -> mqtt.unsubscribe(topic) { _, _ -> } }
        } catch (_: Exception) {}
        super.onStop()
    }

    protected fun refreshMqttSubscriptions() {
        try {
            mqttTopics().forEach { topic -> mqtt.unsubscribe(topic) { _, _ -> } }
            mqttTopics().forEach { topic -> mqtt.subscribe(topic) { _, _ -> } }
        } catch (_: Exception) {}
    }



    protected fun startRecord(view: View, url: String?, isFlag: Int = 0) {

        Log.d("xxxx","=======>${view.width}")
        Log.d("xxxx","height=======>${view.height}")
        if (view.width <= 0 || view.height <= 0) {
            view.doOnLayout {
                startRecord(view, url, isFlag)
            }
            return
        }

        requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        method4(view, url, isFlag)
        mTimerJob = lifecycleScope.launch {
            while (this.isActive) {
                delay(1000)
            }
        }
    }

    protected fun init(view: View, type: Int = 0) {
        var videoBitRate = 1920 * 1080
        var fps = 30
        videoBitRate = 9500_000
        fps = 60

        viewLiveRecord.init(
            window =  requireActivity().window,
            view = view,
            width = view.width,
            fps = fps,
            videoBitRate = videoBitRate,
            iFrameInterval = 1,
            audioBitRate = 192_000,
            audioSampleRate = 44100,
            isStereo = true
        )

    }

    private fun method4(view: View, url: String?, isFlag: Int = 0) {
        init(view, isFlag)
        if (isFlag == 0) {
            if (viewLiveRecord.isStartRecord) {
                Toast.makeText( requireActivity(), "正在推流中", Toast.LENGTH_SHORT).show()
                return
            }
            viewLiveRecord.startLiveRecord(url, { status ->
                Log.i(
                    "xxxx", "viewLiveRecord= onStatusChange() called with: status = $status"
                )
            }, object : EncoderErrorCallback {
                override fun onCodecError(type: String, e: MediaCodec.CodecException) {
                    Log.e("xxxx", "onCodecError() called with: type = $type", e)
                }
            })
        }

    }

    /**
     * 停止推流
     */
    protected fun stopRecord(pauase: Boolean) {
        if (pauase) {
            requireActivity().window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
            stopMethod4()
            mTimerJob?.cancel()
            mTimerJob = null
            // 创建 ImageView
            val imageView = ImageView( requireActivity())
            // 设置 ImageView 的布局参数
            val layoutParams = LinearLayout.LayoutParams(
                MATCH_PARENT,  // 宽度 500px
                MATCH_PARENT // 高度 500px
            )
            imageView.layoutParams = layoutParams

            // 设置图片资源
            imageView.setImageResource(R.mipmap.wait_img) // 替换为你的图片资源
            // 设置缩放类型（可选）
            imageView.scaleType = ImageView.ScaleType.CENTER_CROP
            // 避免拦截事件
            imageView.isFocusable = false
            imageView.isFocusableInTouchMode = false
            imageView.isClickable = false
            imageView.isLongClickable = false
//            _binding.container.addView(imageView)

            // 将 ImageView 添加到根布局

            requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
//            method4(_binding.container, pushStreamBean?.pushUrl.toString())
            mTimerJob = lifecycleScope.launch {
                while (this.isActive) {
                    delay(1000)
                }
            }
        } else {
            requireActivity().window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
            mTimerJob?.cancel()
            mTimerJob = null
            stopMethod4()

        }


    }

    protected fun stopMethod4(): Unit {
        viewLiveRecord.stopRecord()
    }
}